import numpy as np
import cv2
from enum import Enum

class CoordinatesType(Enum):
    """
    Class representing if the coordinates are relative to the
    image size or are absolute values.

        Developed by: Rafael Padilla
        Last modification: Apr 28 2018
    """
    Relative = 1
    Absolute = 2
    
class BBType(Enum):
    """
    Class representing if the bounding box is groundtruth or not.

        Developed by: Rafael Padilla
        Last modification: May 24 2018
    """
    GroundTruth = 1
    Detected = 2

class BBFormat(Enum):
    """
    Class representing the format of a bounding box.
    It can be (X,Y,width,height) => XYWH 
    or (X1,Y1,X2,Y2) => XYX2Y2

        Developed by: Rafael Padilla
        Last modification: May 24 2018
    """
    XYWH = 1
    XYX2Y2 = 2

# size => (width, height) of the image
# box => (X1, X2, Y1, Y2) of the bounding box
def convertToRelativeValues(size, box):
    dw = 1./(size[0])
    dh = 1./(size[1])
    cx = (box[1] + box[0])/2.0 
    cy = (box[3] + box[2])/2.0 
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = cx*dw
    y = cy*dh
    w = w*dw
    h = h*dh
    # x,y => (bounding_box_center)/width_of_the_image
    # w => bounding_box_width / width_of_the_image
    # h => bounding_box_height / height_of_the_image
    return (x,y,w,h)
        
# size => (width, height) of the image
# box => (centerX, centerY, w, h) of the bounding box relative to the image
def convertToAbsoluteValues(size, box):
    w_box = round(size[0] * box[2])
    h_box = round(size[1] * box[3])
    
    xIn = round(((2*float(box[0]) - float(box[2]))*size[0]/2))
    yIn = round(((2*float(box[1]) - float(box[3]))*size[1]/2))

    xEnd = xIn + round(float(box[2])*size[0])
    yEnd = yIn + round(float(box[3])*size[1])

    if xIn < 0:
        xIn = 0
    if yIn < 0:
        yIn = 0
    if xEnd >= size[0]:
        xEnd = size[0]-1
    if yEnd >= size[1]:
        yEnd = size[1]-1
    return (xIn,yIn,xEnd,yEnd)

def add_bb_into_image(image, bb, color=(255,0,0), thickness=2, label=None):
    r = int(color[0])
    g = int(color[1])
    b = int(color[2])

    font = cv2.FONT_HERSHEY_SIMPLEX
    fontScale = 0.5
    fontThickness = 1

    x1,y1,x2,y2 = bb.getAbsoluteBoundingBox(BBFormat.XYX2Y2)
    x1 = int(x1)
    y1 = int(y1)
    x2 = int(x2)
    y2 = int(y2)
    cv2.rectangle(image,(x1,y1),(x2,y2),(b,g,r), thickness)
    # Add label
    if label != None:
        # Get size of the text box
        (tw, th) = cv2.getTextSize(label, font, fontScale, fontThickness)[0]
        # Top-left coord of the textbox
        (xin_bb, yin_bb) = (x1+thickness, y1-th+int(12.5*fontScale))
        # Checking position of the text top-left (outside or inside the bb)
        if yin_bb - th <= 0: # if outside the image
            yin_bb = y1+th # put it inside the bb
        r_Xin = x1-int(thickness/2) 
        r_Yin = y1-th-int(thickness/2) 
        # Draw filled rectangle to put the text in it
        cv2.rectangle(image,(r_Xin,r_Yin-thickness), (r_Xin+tw+thickness*3,r_Yin+th+int(12.5*fontScale)), (b,g,r), -1)
        cv2.putText(image,label, (xin_bb, yin_bb), font, fontScale, (0,0,0), fontThickness, cv2.LINE_AA)
    return image   